#include <stdio.h>
#include <stdint.h>
#include "model.h"
#include "mydata.h"

// mydata implementation list.
extern struct mydata_ops mydata_real;
// extern struct mydata_ops mydata_virt;

// all mydata implementations.
static struct mydata_ops *all_mydata[] = {
    &mydata_real,
    NULL
};

static struct mydata_ops mydata_x;

#define MYDATA_OP(op, ...)					\
	(( mydata_x.op != NULL ) ? mydata_x.op( __VA_ARGS__ )	\
	: (typeof(mydata_x.op(__VA_ARGS__))) 0)

/* Mydata APIs */
int mydata_init(const char *name)
{
    int i;

    for ( i = 0; all_mydata[i] != NULL; i++ ) {
        mydata_x = *all_mydata[i];
        if( strcmp(mydata_x.name, name) == 0 ) {
            break; }
    }
    if(all_mydata[i] == NULL ) {
        fprintf(stderr, "Could not find a available mod:%s\n", name);
	return -1;
    }

    return MYDATA_OP(init, NULL);
}

/** Session **/
// insert
int mydata_insert_session(Session *session) {
    return MYDATA_OP(insert_session, session); }
// remove
int mydata_remove_session(const char *uuid) {
    return MYDATA_OP(remove_session, uuid); }
// verify
int mydata_session_exist(const char *uuid, uint32_t *user_id) {
    return MYDATA_OP(session_exist, uuid, user_id); }
int mydata_session_user_exist(uint32_t user_id, char **uuid) {
    return MYDATA_OP(session_user_exist, user_id, uuid); }
// other

/** User **/
// insert
int mydata_insert_user(User *user) {
    return MYDATA_OP(insert_user, user); }
// update
int mydata_update_user(User *user, uint32_t field) {
    return MYDATA_OP(update_user, user, field); }
// remove
int mydata_remove_user(uint32_t user_id) {
    return MYDATA_OP(remove_user, user_id); }
// verify
int mydata_user_mail_exist(const char *mail, uint32_t *user_id) {
    return MYDATA_OP(user_mail_exist, mail, user_id); }
int mydata_mail_passwd_match(const char *mail, const char *passwd, uint32_t *user_id) {
    return MYDATA_OP(mail_passwd_match, mail, passwd, user_id); }
int mydata_id_passwd_match(uint32_t user_id, const char *passwd) {
    return MYDATA_OP(id_passwd_match, user_id, passwd); }
// get
int mydata_get_user_by_id(uint32_t user_id, User **user) {
    return MYDATA_OP(get_user_by_id, user_id, user); }
int mydata_get_user_by_mail(const char *mail, User **user) {
    return MYDATA_OP(get_user_by_mail, mail, user); }
int mydata_get_user_list(ArrayTable *result) {
    return MYDATA_OP(get_user_list, result); }

/** Note **/
// insert
int mydata_insert_note(Note *note) {
    return MYDATA_OP(insert_note, note); }
// update
int mydata_update_note(Note *note, uint32_t field) {
    return MYDATA_OP(update_note, note, field); }
// remove
int mydata_remove_note(uint64_t note_id) {
    return MYDATA_OP(remove_note, note_id); }
// verify
int mydata_own_note(uint32_t user_id, uint64_t note_id) {
    return MYDATA_OP(own_note, user_id, note_id); }
int mydata_note_is_public(uint64_t note_id) {
    return MYDATA_OP(note_is_public, note_id); }
int mydata_note_is_shared(uint64_t note_id, uint32_t user_id) {
    return MYDATA_OP(note_is_shared, note_id, user_id); }
// get
int mydata_get_note_by_id(uint64_t note_id, Note **note) {
    return MYDATA_OP(get_note_by_id, note_id, note); }
int mydata_get_note_by_uuid(const char *uuid, Note **note) {
    return MYDATA_OP(get_note_by_uuid, uuid, note); }
int mydata_get_all_public_note_number(uint64_t *number) {
    return MYDATA_OP(get_all_public_note_number, number); }
int mydata_get_all_public_note_list(uint64_t start, uint32_t count, ArrayTable *result) {
    return MYDATA_OP(get_all_public_note_list, start, count, result); }
int mydata_get_my_note_number(uint32_t user_id, uint64_t *number) {
    return MYDATA_OP(get_my_note_number, user_id, number); }
int mydata_get_my_note_list(uint32_t user_id, uint64_t start, uint32_t count, ArrayTable *result) {
    return MYDATA_OP(get_my_note_list, user_id, start, count, result); }

/** Tag **/
// insert, update, remove
int mydata_insert_tag(Tag *tag){
    return MYDATA_OP(insert_tag, tag); }
int mydata_remove_tag(uint64_t note_id, const char *tag) {
    return MYDATA_OP(remove_tag, note_id, tag); }
int mydata_remove_tags(uint64_t note_id) {
    return MYDATA_OP(remove_tags, note_id); }
// verify
int mydata_tag_exist(uint64_t note_id, const char *tag) {
    return MYDATA_OP(tag_exist, note_id, tag); }
// get
int mydata_get_tags(uint64_t note_id, ArrayTable *result) {
    return MYDATA_OP(get_tags, note_id, result); }
int mydata_get_tag_list(uint32_t user_id, ArrayTable *result) {
    return MYDATA_OP(get_tag_list, user_id, result); }

/*
int mydata_get_my_note_number(uint32_t my_id, uint32_t *number) {
    return MYDATA_OP(get_my_note_number, my_id, number); }

int mydata_get_my_note_list(uint32_t my_id, uint32_t start, uint32_t count, uint32_t field, NoteArray *result) {
    return MYDATA_OP(get_my_note_list, my_id, start, count, field, result); }

int mydata_get_user_shared_note_number(uint32_t my_id, uint32_t user_id, uint32_t *number) {
    return MYDATA_OP(get_user_shared_note_number, my_id, user_id, number); }

int mydata_get_user_shared_note_list(uint32_t my_id, uint32_t user_id, uint32_t start, uint32_t count, uint32_t field, NoteArray *result) {
    return MYDATA_OP(get_user_shared_note_list, my_id, user_id, start, count, field, result);
}

int mydata_get_all_shared_note_number(uint32_t my_id, uint64_t *number) {
    return MYDATA_OP(get_all_shared_note_number, my_id, number); }

int mydata_get_all_shared_note_list(uint32_t my_id, uint64_t start, uint32_t count, uint32_t field, NoteArray *result) {
    return MYDATA_OP(get_all_shared_note_list, my_id, start, count, field, result); }

int mydata_get_user_public_note_number(uint32_t user_id, uint32_t *number) {
    return MYDATA_OP(get_user_public_note_number, user_id, number); }

int mydata_get_user_public_note_list(uint32_t user_id, uint32_t start, uint32_t count, uint32_t field, NoteArray *result) {
    return MYDATA_OP(get_user_public_note_list, user_id, start, count, field, result); }

int mydata_get_all_public_note_number(uint64_t *number) {
    return MYDATA_OP(get_all_public_note_number, number); }

int mydata_get_all_public_note_list(uint64_t start, uint32_t count, uint32_t field, NoteArray *result) {
    return MYDATA_OP(get_all_public_note_list, start, count, field, result); }

int mydata_get_user_by_id(uint32_t my_id, uint32_t user_id, uint32_t field, User **user) {
    return MYDATA_OP(get_user_by_id, my_id, user_id, field, user); }

int mydata_get_user_by_mail(uint32_t my_id, char *mail, uint32_t field, User **user) {
    return MYDATA_OP(get_user_by_mail, my_id, mail, field, user); }

int mydata_get_user_number(uint32_t my_id, uint32_t *number) {
    return MYDATA_OP(get_user_number, my_id, number); }

int mydata_get_user_list(uint32_t my_id, uint32_t start, uint32_t count, uint32_t field, UserArray *result) {
    return MYDATA_OP(get_user_list, my_id, start, count, field, result); }

int mydata_get_note_by_uuid(uint32_t my_id, char *uuid, uint32_t field, Note **note) {
    return MYDATA_OP(get_note_by_uuid, my_id, uuid, field, note); }
*/

